package com.liuhouse.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.liuhouse.constants.SystemCanstants;
import com.liuhouse.pojo.Menu;
import com.liuhouse.mapper.MenuMapper;
import com.liuhouse.service.IMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liuhouse.utils.BeanCopyUtils;
import com.liuhouse.vo.MenuVo;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author liuhouse
 * @since 2024-01-27
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    //查询用户的权限信息
    @Override
    public List<String> selectPermsByUserId(Long id) {
        //根据用户id查询用户的权限信息,用户id为1代表管理员,如果是管理员就返回所有的权限
        if(id == 1L){
            LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Menu::getMenuType , SystemCanstants.TYPE_MENU , SystemCanstants.TYPE_BUTTON);
            wrapper.eq(Menu::getStatus , SystemCanstants.STATUS_NORMAL);
            List<Menu> menus = list(wrapper);
            //这个lambda表达式 自己写 成功了 就都可以了
            //开始  得到 权限标识信息
            List<String> perms = menus.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
            return perms;
        }
        //如果不是管理员就返回对应用户所具有的权限
        List<String> otherPerms = getBaseMapper().selectPermsByOtherUserId(id);
        return otherPerms;
    }

    //查询用户的路由信息(权限菜单)
    @Override
    public List<Menu> selectRouterMenuTreeByUserId(Long userId) {
        //1.判断是否是超级管理员,用户id为1，代表的是超级管理员,如果是就返回所有符合要求的权限菜单
        //这里使用的是自定义的方法  写的原生sql语句  正常情况下确实是应该注入使用  但是  这里是确实提供了方法 其实是一个效果
        MenuMapper menuMapper = getBaseMapper();
        //查询的菜单列表
        List<Menu> menus = null;
        //当前身份是管理员
        if(userId.equals(1L)){
            menus = menuMapper.selectAllRouterMenu();
        }else{ //2.如果不是超级管理员,就查询对应用户所具有的路由信息(权限菜单)
            menus = menuMapper.selectOtherRouterMenuTreeByUserId(userId);
        }
        //3构建tree,也就是子父菜单树，有层级关系
        //思路:先找出第一层的菜单,然后再找出子菜单(也就是第二层),把子菜单的结果赋值给Menu类的children字段
        List<Menu> menuTree = xxBuildMenuTree(menus , 0L);
        return menuTree;
    }

    //查询所有的菜单
    @Override
    public List<MenuVo> selectMenuList(Menu menu) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        //对菜单名称进行模糊查询
        queryWrapper.like(StringUtils.hasText(menu.getMenuName()) , Menu::getMenuName , menu.getMenuName());
        //对状态进行查询
        queryWrapper.eq(StringUtils.hasText(menu.getStatus()) , Menu::getStatus , menu.getStatus());
        //对菜单数据进行排序 , 根据多个字段进行排序
        queryWrapper.orderByAsc(Menu::getParentId , Menu::getOrderNum);
        //直接查询出所有的数据
        List<Menu> list = list(queryWrapper);
        //进行数据转换 , 将数据转换 全部返回的数据  前端会自己进行处理
        List<MenuVo> menuVoList = BeanCopyUtils.copyBeanList(list, MenuVo.class);
        return menuVoList;
    }

    @Override
    public boolean hasChild(Long menuId) {
        LambdaQueryWrapper<Menu> menuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        menuLambdaQueryWrapper.eq(Menu::getParentId , menuId);
        long count = count(menuLambdaQueryWrapper);
        return count != 0;
    }

    //修改角色 - 根据角色id查询对应的角色菜单列表树
    @Override
    public List<Long> selectMenuListByRoleId(Long roleId) {
        return getBaseMapper().selectMenuListByRoleId(roleId);
    }

    private List<Menu> xxBuildMenuTree(List<Menu> menus, long parentId) {
        List<Menu> menuTree = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> menu.setChildren(xxgetChildren(menu , menus)))
                .collect(Collectors.toList());
        return menuTree;
    }


    //用于获取传入参数的子菜单,并封装为LIST集合返回
    private List<Menu> xxgetChildren(Menu menu, List<Menu> menus) {
        List<Menu> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                //如果有三层菜单的话，也就是子菜单的子菜单,那么我们就使用下面的那行递归(自己调用自己)来处理
                .map(m -> m.setChildren(xxgetChildren(m, menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
}
